package org.budo.compress.tar;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.budo.compress.AbstractCompressor;
import org.budo.support.lang.util.IoUtil;

/**
 * @author lmw
 */
public class TarCompressor extends AbstractCompressor {
    @Override
    public void compress(File dir, File to) {
        try {
            String parentPath = "";
            TarArchiveOutputStream tarTo = new TarArchiveOutputStream(new FileOutputStream(to));
            tarTo.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);

            this._tar(dir, tarTo, parentPath);

            tarTo.close(); // 手动关闭
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    private void _tarDir(File dir, TarArchiveOutputStream tarTo, String parentPath) throws Throwable {
        String thisPath = parentPath.isEmpty() ? dir.getName() : parentPath + File.separator + dir.getName();

        File[] _listFiles = dir.listFiles();
        if (_listFiles == null || _listFiles.length == 0) {
            TarArchiveEntry tarArchiveEntry = new TarArchiveEntry(thisPath);
            tarTo.putArchiveEntry(tarArchiveEntry); // 空文件夹的处理
            tarTo.closeArchiveEntry();
            return;
        }

        for (File file : _listFiles) {
            this._tar(file, tarTo, thisPath);
        }
    }

    private void _tarFile(File file, TarArchiveOutputStream tarTo, String parentPath) throws Throwable {
        String thisPath = parentPath + File.separator + file.getName();

        TarArchiveEntry archiveEntry = new TarArchiveEntry(thisPath); // 如果打包不需要文件夹，就用 new TarArchiveEntry(file.getName())
        archiveEntry.setSize(file.length());
        tarTo.putArchiveEntry(archiveEntry);

        FileInputStream inputStream = new FileInputStream(file);
        IoUtil.write(inputStream, tarTo, false, true);
        inputStream.close();

        tarTo.closeArchiveEntry(); // 结束写一个 Entry
    }

    protected void _tar(File from, TarArchiveOutputStream tarTo, String parentPath) throws Throwable {
        if (null == from || !from.exists()) {
            throw new RuntimeException("#61 from not exists, from=" + from);
        }

        if (from.isFile()) {
            this._tarFile(from, tarTo, parentPath);
            return;
        }

        if (from.isDirectory()) {
            this._tarDir(from, tarTo, parentPath);
            return;
        }

        throw new RuntimeException("#0 not file not dir, " + from);
    }

    @Override
    public void decompress(File from, File to) {
        throw new RuntimeException();
    }
}